﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Globalization
Imports System.Net
Imports System.Reflection
Imports System.Web.Services.Protocols
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.Activities
    <ActivityValidator(GetType(InvokeWebServiceValidator)), SRCategory("Standard"), SRDescription("InvokeWebServiceActivityDescription"), ToolboxItem(GetType(InvokeWebServiceToolboxItem)), Designer(GetType(InvokeWebServiceDesigner), GetType(IDesigner)), ToolboxBitmap(GetType(InvokeWebServiceActivity), "Resources.WebServiceInOut.png")> _
    Public NotInheritable Class InvokeWebServiceActivity
        Inherits Activity
        Implements IPropertyValueProvider, IDynamicPropertyTypeProvider
        ' Events
        <SRDescription("OnAfterMethodInvokeDescr"), MergableProperty(False), SRCategory("Handlers")> _
        Public Custom Event Invoked As EventHandler([Of] InvokeWebServiceEventArgs)
            AddHandler(ByVal value As EventHandler([Of] InvokeWebServiceEventArgs))
                MyBase.AddHandler(InvokeWebServiceActivity.InvokedEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler([Of] InvokeWebServiceEventArgs))
                MyBase.RemoveHandler(InvokeWebServiceActivity.InvokedEvent, value)
            End RemoveHandler
        End Event
        <MergableProperty(False), SRCategory("Handlers"), SRDescription("OnBeforeMethodInvokeDescr")> _
        Public Custom Event Invoking As EventHandler([Of] InvokeWebServiceEventArgs)
            AddHandler(ByVal value As EventHandler([Of] InvokeWebServiceEventArgs))
                MyBase.AddHandler(InvokeWebServiceActivity.InvokingEvent, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler([Of] InvokeWebServiceEventArgs))
                MyBase.RemoveHandler(InvokeWebServiceActivity.InvokingEvent, value)
            End RemoveHandler
        End Event

        ' Methods
        Public Sub New()
            MyBase.SetReadOnlyPropertyValue(InvokeWebServiceActivity.ParameterBindingsProperty, New WorkflowParameterBindingCollection(Me))
        End Sub

        Public Sub New(ByVal name As String)
            MyBase.New(name)
            MyBase.SetReadOnlyPropertyValue(InvokeWebServiceActivity.ParameterBindingsProperty, New WorkflowParameterBindingCollection(Me))
        End Sub

        Protected NotOverridable Overrides Function Execute(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If ((Me.SessionId <> "") AndAlso (Not Me.SessionId Is Nothing)) Then
                Me.PopulateSessionCookie
            End If
            Dim proxyInstance As Object = Activator.CreateInstance(Me.ProxyClass)
            Dim protocol As HttpWebClientProtocol = [TryCast](proxyInstance,HttpWebClientProtocol)
            protocol.CookieContainer = Me.SessionCookieContainer
            MyBase.RaiseGenericEvent([Of] InvokeWebServiceEventArgs)(InvokeWebServiceActivity.InvokingEvent, Me, New InvokeWebServiceEventArgs(proxyInstance))
            Dim method As MethodInfo = Me.ProxyClass.GetMethod(Me.MethodName, (BindingFlags.Public Or BindingFlags.Instance))
            Dim parameters As Object() = InvokeHelper.GetParameters(method, Me.ParameterBindings)
            Dim binding As WorkflowParameterBinding = Nothing
            If Me.ParameterBindings.Contains("(ReturnValue)") Then
                binding = Me.ParameterBindings.Item("(ReturnValue)")
            End If
            Dim obj3 As Object = Nothing
            Try 
                obj3 = Me.ProxyClass.InvokeMember(Me.MethodName, (BindingFlags.InvokeMethod Or (BindingFlags.Public Or BindingFlags.Instance)), Nothing, proxyInstance, parameters, CultureInfo.InvariantCulture)
            Catch exception As TargetInvocationException
                If (Not exception.InnerException Is Nothing) Then
                    Throw exception.InnerException
                End If
                Throw
            End Try
            If (Not binding Is Nothing) Then
                binding.Value = obj3
            End If
            InvokeHelper.SaveOutRefParameters(parameters, method, Me.ParameterBindings)
            MyBase.RaiseGenericEvent([Of] InvokeWebServiceEventArgs)(InvokeWebServiceActivity.InvokedEvent, Me, New InvokeWebServiceEventArgs(proxyInstance))
            Return ActivityExecutionStatus.Closed
        End Function

        Friend Sub GetParameterPropertyDescriptors(ByVal properties As IDictionary)
            If (Not Me.Site Is Nothing) Then
                If (DirectCast(Me.Site.GetService(GetType(ITypeProvider)), ITypeProvider) Is Nothing) Then
                    Throw New InvalidOperationException(SR.GetString("General_MissingService", New Object() { GetType(ITypeProvider).FullName }))
                End If
                Dim proxyClass As Type = Me.ProxyClass
                If (Not proxyClass Is Nothing) Then
                    Dim method As MethodInfo = proxyClass.GetMethod(Me.MethodName)
                    If (Not method Is Nothing) Then
                        Dim list As New ArrayList(method.GetParameters)
                        If (Not method.ReturnType Is GetType(Void)) Then
                            list.Add(method.ReturnParameter)
                        End If
                        Dim info2 As ParameterInfo
                        For Each info2 In list
                            If (info2.ParameterType Is Nothing) Then
                                [Continue] For
                            End If
                            Dim descriptor As PropertyDescriptor = Nothing
                            If (info2.Position = -1) Then
                                descriptor = New ParameterInfoBasedPropertyDescriptor(GetType(InvokeWebServiceActivity), info2, False, New Attribute() { DesignOnlyAttribute.Yes })
                            Else
                                descriptor = New ParameterInfoBasedPropertyDescriptor(GetType(InvokeWebServiceActivity), info2, InvokeWebServiceActivity.ReservedParameterNames.Contains(info2.Name), New Attribute() { DesignOnlyAttribute.Yes })
                            End If
                            properties.Item(descriptor.Name) = descriptor
                        Next
                    End If
                End If
            End If
        End Sub

        Private Function GetRootActivity() As Activity
            Dim parent As Activity = Me
            Do While (Not parent.Parent Is Nothing)
                parent = parent.Parent
            Loop
            Return parent
        End Function

        Protected Overrides Sub OnClosed(ByVal provider As IServiceProvider)
            MyBase.RemoveProperty(InvokeWebServiceActivity.SessionCookieContainerProperty)
            MyBase.RemoveProperty(InvokeWebServiceActivity.SessionCookieMapProperty)
        End Sub

        Private Sub PopulateSessionCookie()
            If (Me.SessionCookieContainer Is Nothing) Then
                Dim container As CookieContainer
                Dim rootActivity As Activity = Me.GetRootActivity
                Dim dictionary As Dictionary([Of] String, CookieContainer) = DirectCast(rootActivity.GetValue(InvokeWebServiceActivity.SessionCookieMapProperty), Dictionary([Of] String, CookieContainer))
                If (dictionary Is Nothing) Then
                    dictionary = New Dictionary([Of] String, CookieContainer)
                    rootActivity.SetValue(InvokeWebServiceActivity.SessionCookieMapProperty, dictionary)
                    container = New CookieContainer
                    dictionary.Add(Me.SessionId, container)
                ElseIf Not dictionary.TryGetValue(Me.SessionId, container) Then
                    container = New CookieContainer
                    dictionary.Add(Me.SessionId, container)
                End If
                Me.SessionCookieContainer = container
            End If
        End Sub

        Private Function System.Workflow.ComponentModel.Design.IPropertyValueProvider.GetPropertyValues(ByVal context As ITypeDescriptorContext) As ICollection Implements IPropertyValueProvider.GetPropertyValues
            Dim service As ITypeProvider = DirectCast(context.GetService(GetType(ITypeProvider)), ITypeProvider)
            If (service Is Nothing) Then
                Throw New InvalidOperationException(SR.GetString("General_MissingService", New Object() { GetType(ITypeProvider).FullName }))
            End If
            Dim is2 As ICollection = Nothing
            If (context.PropertyDescriptor.Name = "ProxyClass") Then
                Dim list As New List([Of] Type)
                Dim o As Type = service.GetType(GetType(SoapHttpClientProtocol).FullName)
                If (Not o Is Nothing) Then
                    Dim type2 As Type
                    For Each type2 In service.GetTypes
                        If (Not type2.Equals(o) AndAlso TypeProvider.IsAssignable(o, type2)) Then
                            list.Add(type2)
                        End If
                    Next
                End If
                Return list.ToArray
            End If
            If Not (context.PropertyDescriptor.Name = "MethodName") Then
                Return is2
            End If
            Dim strings As New StringCollection
            Dim proxyClass As Type = Me.ProxyClass
            If (Not proxyClass Is Nothing) Then
                Dim info As MethodInfo
                For Each info In proxyClass.GetMethods((BindingFlags.Public Or (BindingFlags.Instance Or BindingFlags.DeclaredOnly)))
                    Dim customAttributes As Object() = info.GetCustomAttributes(GetType(SoapDocumentMethodAttribute), False)
                    If ((customAttributes Is Nothing) OrElse (customAttributes.Length = 0)) Then
                        customAttributes = info.GetCustomAttributes(GetType(SoapRpcMethodAttribute), False)
                    End If
                    If ((Not customAttributes Is Nothing) AndAlso (customAttributes.Length > 0)) Then
                        strings.Add(info.Name)
                    End If
                Next
            End If
            Return strings
        End Function

        Private Function System.Workflow.ComponentModel.IDynamicPropertyTypeProvider.GetAccessType(ByVal serviceProvider As IServiceProvider, ByVal propertyName As String) As AccessTypes Implements IDynamicPropertyTypeProvider.GetAccessType
            If (propertyName Is Nothing) Then
                Throw New ArgumentNullException("propertyName")
            End If
            Return AccessTypes.Read
        End Function

        Private Function System.Workflow.ComponentModel.IDynamicPropertyTypeProvider.GetPropertyType(ByVal serviceProvider As IServiceProvider, ByVal propertyName As String) As Type Implements IDynamicPropertyTypeProvider.GetPropertyType
            If (propertyName Is Nothing) Then
                Throw New ArgumentNullException("propertyName")
            End If
            Dim properties As New Dictionary([Of] String, Object)
            Me.GetParameterPropertyDescriptors(properties)
            If properties.ContainsKey(propertyName) Then
                Dim descriptor As ParameterInfoBasedPropertyDescriptor = [TryCast](properties.Item(propertyName),ParameterInfoBasedPropertyDescriptor)
                If (Not descriptor Is Nothing) Then
                    Return descriptor.ParameterType
                End If
            End If
            Return Nothing
        End Function


        ' Properties
        <SRCategory("Activity"), MergableProperty(False), DefaultValue(""), RefreshProperties(RefreshProperties.All), SRDescription("MethodNameDescr"), TypeConverter(GetType(PropertyValueProviderTypeConverter))> _
        Public Property MethodName As String
            Get
                Return [TryCast](MyBase.GetValue(InvokeWebServiceActivity.MethodNameProperty),String)
            End Get
            Set(ByVal value As String)
                MyBase.SetValue(InvokeWebServiceActivity.MethodNameProperty, value)
            End Set
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
        Public ReadOnly Property ParameterBindings As WorkflowParameterBindingCollection
            Get
                Return [TryCast](MyBase.GetValue(InvokeWebServiceActivity.ParameterBindingsProperty),WorkflowParameterBindingCollection)
            End Get
        End Property

        <RefreshProperties(RefreshProperties.All), SRDescription("ProxyClassDescr"), TypeConverter(GetType(TypePropertyValueProviderTypeConverter)), MergableProperty(False), DefaultValue(CStr(Nothing)), SRCategory("Activity")> _
        Public Property ProxyClass As Type
            Get
                Return [TryCast](MyBase.GetValue(InvokeWebServiceActivity.ProxyClassProperty),Type)
            End Get
            Set(ByVal value As Type)
                MyBase.SetValue(InvokeWebServiceActivity.ProxyClassProperty, value)
            End Set
        End Property

        Friend Property SessionCookieContainer As CookieContainer
            Get
                Return DirectCast(MyBase.GetValue(InvokeWebServiceActivity.SessionCookieContainerProperty), CookieContainer)
            End Get
            Set(ByVal value As CookieContainer)
                MyBase.SetValue(InvokeWebServiceActivity.SessionCookieContainerProperty, value)
            End Set
        End Property

        <DefaultValue(""), MergableProperty(False), SRCategory("Activity"), SRDescription("WebServiceSessionIDDescr")> _
        Public Property SessionId As String
            Get
                Return [TryCast](MyBase.GetValue(InvokeWebServiceActivity.SessionIdProperty),String)
            End Get
            Set(ByVal value As String)
                MyBase.SetValue(InvokeWebServiceActivity.SessionIdProperty, value)
            End Set
        End Property


        ' Fields
        Public Shared ReadOnly InvokedEvent As DependencyProperty = DependencyProperty.Register("Invoked", GetType(EventHandler([Of] InvokeWebServiceEventArgs)), GetType(InvokeWebServiceActivity))
        Public Shared ReadOnly InvokingEvent As DependencyProperty = DependencyProperty.Register("Invoking", GetType(EventHandler([Of] InvokeWebServiceEventArgs)), GetType(InvokeWebServiceActivity))
        Public Shared ReadOnly MethodNameProperty As DependencyProperty = DependencyProperty.Register("MethodName", GetType(String), GetType(InvokeWebServiceActivity), New PropertyMetadata("", DependencyPropertyOptions.Metadata))
        Public Shared ReadOnly ParameterBindingsProperty As DependencyProperty = DependencyProperty.Register("ParameterBindings", GetType(WorkflowParameterBindingCollection), GetType(InvokeWebServiceActivity), New PropertyMetadata((DependencyPropertyOptions.Metadata Or DependencyPropertyOptions.ReadOnly), New Attribute() { New BrowsableAttribute(False), New DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }))
        Public Shared ReadOnly ProxyClassProperty As DependencyProperty = DependencyProperty.Register("ProxyClass", GetType(Type), GetType(InvokeWebServiceActivity), New PropertyMetadata(Nothing, DependencyPropertyOptions.Metadata))
        Friend Shared ReadOnly ReservedParameterNames As ArrayList = New ArrayList(New String() { "Name", "Enabled", "Description", "MethodName", "ProxyClass", "SessionId", "Invoked", "Invoking" })
        Private Shared SessionCookieContainerProperty As DependencyProperty = DependencyProperty.Register("SessionCookieContainer", GetType(CookieContainer), GetType(InvokeWebServiceActivity))
        Private Shared SessionCookieMapProperty As DependencyProperty = DependencyProperty.RegisterAttached("SessionCookieMap", GetType(Dictionary([Of] String, CookieContainer)), GetType(InvokeWebServiceActivity))
        Public Shared ReadOnly SessionIdProperty As DependencyProperty = DependencyProperty.Register("SessionId", GetType(String), GetType(InvokeWebServiceActivity), New PropertyMetadata("", DependencyPropertyOptions.Metadata))
        Private Shared ReadOnly WebServiceInvoker As Guid = New Guid("C3FE5ABC-7D41-4064-810E-42BEF0A855EC")
    End Class
End Namespace

